;********************************************************************
;*          MultiSioAsmArm.s                                        *
;*            Multi-play Communication Library (ARMASM)             *
;*   (Timer Interrupt Send & Non-adjustment of Synchronization)     *
;*                                                                  *
;*          Copyright (C) 1999-2001 NINTENDO Co.,Ltd.               *
;********************************************************************
    INCLUDE     AgbDefineArm.s
    INCLUDE     AgbMemoryMapArm.s
    INCLUDE     AgbSyscallDefineArm.s
    INCLUDE     AgbMacroArm.s
    AREA        Init, CODE, READONLY

    INCLUDE     MultiSioDefineArm.s


    IF :DEF: MULTI_SIO_DI_FUNC_FAST

;--------------------------------------------------------------------
;               Update Receive Data/Check Buffer Routine            -
;--------------------------------------------------------------------

    EXTERN      Ms
    GLOBAL      MultiSioRecvBufChange
    CODE32
MultiSioRecvBufChange
        stmfd   sp!, {r4-r11}

        mov     r12, #REG_BASE                      ; r12: REG_BASE
        ldr     r11, =Ms                            ; r11: &Ms
        add     r10, r11, #OFS_MS_LAST_RECV_BUF_P   ; r10: &Ms.LastRecvBufp[0]
        mov     r9,  #1                             ; r9:  1
        mov     r8,  #0                             ; r8:  0


        ; *(vu8 *)REG_IME = 0   Disable Interrupt (29 Clocks)

        strb    r8,  [r12, #OFFSET_REG_IME]

        ; Ms.RecvCheckBufp[i] <--> Ms.LastRecvBufp[i]

        ldmia   r10,  {r0-r7}
        stmia   r10!, {r4-r7}
        stmia   r10!, {r0-r3}

        ; SyncRecvFlagBak[i] = Ms.SyncRecvFlag[i]
        ; Ms.SyncRecvFlag[i] = 0

        ldr     r0,  [r11, #OFS_MS_SYNC_RECV_FLAG]
        str     r8,  [r11, #OFS_MS_SYNC_RECV_FLAG]

        ; *(vu8 *)REG_IME = 1   Enable Interrupt

        strb    r9,  [r12, #OFFSET_REG_IME]

        ; return  Ms.SyncRecvFlag[i]

        ldmfd   sp!, {r4-r11}
        bx      lr

    LTORG                                           ; Create Literal Pool


;--------------------------------------------------------------------
;                   Multi-play Communication Interrupt Rountine     -
;--------------------------------------------------------------------

    GLOBAL      MultiSioIntr
    CODE32
MultiSioIntr

        ; Save Receive Data

        ; *(u64 *)RecvTmp = *(u64 *)REG_SIOMLT_RECV

        mov     r12, #REG_BASE                           ; r12: REG_SIOMLT_RECV
        add     r12, r12, #OFFSET_REG_SIOMLT_RECV
        ldmia   r12, {r0-r1}

        ; Save Register to Stack

        stmfd   sp!, {r7-r11}


        ldr     r11, =Ms                                ; r11: &Ms
        ldr     r9,  =MULTI_SIO_SYNC_DATA               ; r9:  MULTI_SIO_SYNC_DATA


        ; Send Data Processing

        ; if  (Ms.SendBufCounter == -1) {

        ldr     r10, [r11, #OFS_MS_SEND_BUF_COUNTER]    ; r10: Ms.SendBufCounter
        adds    r3,  r10, #1
        strlt   r3, [r12, #0]
        blt     %f3
        bne     %f2

        ;     REG_SIOCNT->Data = MULTI_SIO_SYNC_DATA          Set Synchronization Data

        strh    r9, [r12, #REG_SIOMLT_SEND - REG_SIOMLT_RECV]

        ;     Ms.CurrentSendBufp <--> Ms.NextSendBufp         Change Send Buffer

        add     r8,  r11, #OFS_MS_NEXT_SEND_BUF_P
        ldmia   r8, {r2,r3}
        mov     r7,  r2
        stmia   r8, {r3,r7}
        b       %f3
2
        ; } else if (Ms.SendBufCounter >= 0) {
        ;     REG_SIOCNT->Data = Ms.CurrentSendBufp[Ms.SendBufCounter]
        ;                                                     Set Send Data

        ldr     r3, [r11, #OFS_MS_CURRENT_SEND_BUF_P]
        ldr     r2, [r3,  r10, lsl #1]
        strh    r2, [r12, #REG_SIOMLT_SEND - REG_SIOMLT_RECV]
3
        ; }

        ; if (Ms.SendBufCounter < sizeof(MultiSioPacket)/2 - 1)
        ;     Ms.SendBufCounter++;

        cmp     r10, #MULTI_SIO_PACKET_SIZE/2 - 1
        addlt   r10, r10, #1
        strlt   r10, [r11, #OFS_MS_SEND_BUF_COUNTER]

        ; ave Receive Data & Register to Stack

        stmfd   sp!, {r0-r1, r5-r6}



        ; Receive Data Processing (Max. Approx. 160 Clocks/Included in Wait Period)

        ; for (i=0; i<MULTI_SIO_PLAYERS_MAX; i++) {

        mov     r6, #MULTI_SIO_PLAYERS_MAX - 1          ; r6:  i
4
        add     r8, r11, #OFS_MS_RECV_BUF_COUNTER       ; r8: &Ms.RecvBufCounter[i]
        add     r8, r8, r6, lsl #2
        ldr     r10, [r8, #0]                           ; r10: Ms.RecvBufCounter[i]
        mov     r3, r6, lsl #1                          ; r5:  RecvTmp[i]
        ldrh    r5,  [sp, r3]

        ; if ( RecvTmp[i] == MULTI_SIO_SYNC_DATA
        ;   && Ms.RecvBufCounter[i] > sizeof(MultiSioPacket)/2 - 3) {

        cmp     r5, r9
        bne     %f6
        cmp     r10, #MULTI_SIO_PACKET_SIZE/2 - 3
        ble     %f6

        ;      Ms.RecvBufCounter[i] = -1

        mov     r0, #1
        sub     r10, r0, #2

        b       %f7
6
        ; } else {
        ;     Ms.CurrentRecvBufp[i][Ms.RecvBufCounter[i]] = RecvTmp[i]
        ;                                                     Store Receive Data

        ldr     r0, [r8, #OFS_MS_CURRENT_RECV_BUF_P - OFS_MS_RECV_BUF_COUNTER]
        mov     r3, r10, lsl #1
        strh    r5, [r0, r3]

        ; if (Ms.RecvBufCounter[i] == sizeof(MultiSioPacket)/2 - 3)

        cmp     r10, #MULTI_SIO_PACKET_SIZE/2 - 3
        bne     %f7

        ;     Ms.CurrentRecvBufp[i] <--> Ms.LastRecvBufp[i]   Change Receive Buffer

        ldr     r1, [r8, #OFS_MS_LAST_RECV_BUF_P    - OFS_MS_RECV_BUF_COUNTER]
        str     r0, [r8, #OFS_MS_LAST_RECV_BUF_P    - OFS_MS_RECV_BUF_COUNTER]
        str     r1, [r8, #OFS_MS_CURRENT_RECV_BUF_P - OFS_MS_RECV_BUF_COUNTER]

        ;     Ms.SyncRecvFlag[i] = 1;                         Receive Completion Flag

        add     r3, r11, #OFS_MS_SYNC_RECV_FLAG
        mov     r0, #1
        strb    r0, [r3, r6]
7
        ; }

        ; if (Ms.RecvBufCounter[i] < sizeof(MultiSioPacket)/2 - 1)
        ;     Ms.RecvBufCounter[i]++;

        cmp     r10, #MULTI_SIO_PACKET_SIZE/2 - 1
        addlt   r10, r10, #1
        str     r10, [r8, #0]

        subs    r6, r6, #1
        bge     %b4

        ; }



        ; Start Master Send

        ; if (Ms.Type == SIO_MULTI_PARENT)

        ldrb    r0, [r11,#OFS_MS_TYPE]
        cmp     r0, #0
        beq     %f11

        ;     *(vu16 *)REG_SIOCNT |= SIO_ENABLE;

        ldrh    r0, [r12, #REG_SIOCNT - REG_SIOMLT_RECV]
        orr     r0, r0, #SIO_ENABLE
        strh    r0, [r12, #REG_SIOCNT - REG_SIOMLT_RECV]

11
        add     sp, sp, #8
        ldmfd   sp!, {r5-r11}
        bx      lr


    ENDIF


    END

